package pt.mleiria.crypto;

import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.Map;

import pt.mleiria.bit.Utils;

public class CryptoUtils {

	public static final char[] alfabet = { 'A', 'B', 'C', 'D', 'E', 'F', 'G',
			'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
			'U', 'V', 'W', 'Y', 'X', 'Z' };
	public final static int alfabetLength = alfabet.length;
	public static final Map<Character, Integer> alfabetMap = new HashMap<Character, Integer>(
			26);

	static {
		int i = 0;
		for (char letter : alfabet) {
			alfabetMap.put(letter, i++);
		}
	}

	public static char getLetter(int index) {
		return alfabet[index];
	}

	/**
	 * If necessary, add bits with value 0 to the end of the data until the
	 * padded data is a multiple of n. (If the original data was already a
	 * multiple of n, no bits are added.)
	 */
	public static final int PAD_ISO9797_M1 = 1;
	/**
	 * Add a single bit with value 1 to the end of the data. Then if necessary
	 * add bits with value 0 to the end of the data until the padded data is a
	 * multiple of n.
	 */
	public static final int PAD_ISO9797_M2 = 2;
	/**
	 * The padded data comprises (in this order): - The length of the unpadded
	 * data (in bits) expressed in big-endian binary in n bits (i.e. one cipher
	 * block) - The unpadded data - As many (possibly none) bits with value 0 as
	 * are required to bring the total length to a multiple of n bits It is not
	 * necessary to transmit or store the padding bits, because the recipient
	 * can regenerate them, knowing the length of the unpadded data and the
	 * padding method used
	 */
	public static final int PAD_ISO9797_M3 = 3;

	/**
	 * 
	 * @param input
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String cipherAndEncodeBase64SHA1(final String input)
			throws UnsupportedEncodingException {
		MessageDigest SHA1 = null;
		try {
			SHA1 = MessageDigest.getInstance("SHA-1");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		SHA1.reset();
		SHA1.update(input.getBytes("UTF-8"));
		byte[] encoded = Utils.encodeBase64(SHA1.digest());
		final String base64 = new String(encoded);
		System.out.println(SHA1.getProvider().getInfo());
		return base64;
	}
	/**
	 * 
	 * @param input
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String cipherSHA1(final String input)	throws UnsupportedEncodingException {
		MessageDigest SHA1 = null;
		try {
			SHA1 = MessageDigest.getInstance("SHA-1");
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		SHA1.reset();
		final byte[] block = input.getBytes();
		SHA1.update(block);
		final byte[] cipheredBlock = SHA1.digest(); 
		return toStringBlock(cipheredBlock, 0, cipheredBlock.length).toUpperCase();
	}

	/**
	 * Convert a block to a String representation.
	 * 
	 * @param block
	 *            The source block
	 * @param off
	 *            The source offset
	 * @param len
	 *            The lenth to convert
	 * @return a String representation of the source block
	 */
	public static String toStringBlock(byte[] block, int off, int len) {
		String hexits = "0123456789abcdef";
		StringBuffer buf = new StringBuffer();
		for (int i = off; i < off + len; ++i) {
			buf.append(hexits.charAt((block[i] >>> 4) & 0xf));
			buf.append(hexits.charAt(block[i] & 0xf));
		}
		return buf.toString();
	}
}
